This tutorial … Scottish Remote Sensing Portal.

Packages

library(lidR)# process LAZ files
library(raster)# deal with raster
library(rayshader) # 3D viz
library(rgl) # interactive plot
library(sf) # spatial class

Area of Interest

motte_point = st_read("data/canmore_point.shp", quiet = TRUE)

motte_buffer = st_buffer(motte_point,dist = 50)

LAZ

Next, I am reading the LAZ files and clipping the point cloud to the extent of immidiate area around the motte.

#read laz files
las = readLAS("data/NX6055_4PPM_LAS_PHASE3.laz")

motte = clip_roi(las, motte_buffer)
#plot lidar point cloud
plot(motte, bg = "white")

rglwidget()

grab and rotate the model !

Digital Elevetion Model

In this step I am running standard alghoritms from LiDR package to compute Digital Surface Model (DSM) and Digitial Terrain Model (DTM).

rgl.clear()
# create dsm and dtm
dsm = grid_canopy(motte, 0.5, pitfree())

# assign coordinate system
crs(dsm) = CRS("+init=epsg:27700")
## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj =
## prefer_proj): Discarded datum OSGB_1936 in CRS definition
st_crs(27700)
## Coordinate Reference System:
##   User input: EPSG:27700 
##   wkt:
## PROJCRS["OSGB 1936 / British National Grid",
##     BASEGEOGCRS["OSGB 1936",
##         DATUM["OSGB 1936",
##             ELLIPSOID["Airy 1830",6377563.396,299.3249646,
##                 LENGTHUNIT["metre",1]]],
##         PRIMEM["Greenwich",0,
##             ANGLEUNIT["degree",0.0174532925199433]],
##         ID["EPSG",4277]],
##     CONVERSION["British National Grid",
##         METHOD["Transverse Mercator",
##             ID["EPSG",9807]],
##         PARAMETER["Latitude of natural origin",49,
##             ANGLEUNIT["degree",0.0174532925199433],
##             ID["EPSG",8801]],
##         PARAMETER["Longitude of natural origin",-2,
##             ANGLEUNIT["degree",0.0174532925199433],
##             ID["EPSG",8802]],
##         PARAMETER["Scale factor at natural origin",0.9996012717,
##             SCALEUNIT["unity",1],
##             ID["EPSG",8805]],
##         PARAMETER["False easting",400000,
##             LENGTHUNIT["metre",1],
##             ID["EPSG",8806]],
##         PARAMETER["False northing",-100000,
##             LENGTHUNIT["metre",1],
##             ID["EPSG",8807]]],
##     CS[Cartesian,2],
##         AXIS["(E)",east,
##             ORDER[1],
##             LENGTHUNIT["metre",1]],
##         AXIS["(N)",north,
##             ORDER[2],
##             LENGTHUNIT["metre",1]],
##     USAGE[
##         SCOPE["unknown"],
##         AREA["UK - Britain and UKCS 49°46'N to 61°01'N, 7°33'W to 3°33'E"],
##         BBOX[49.75,-9.2,61.14,2.88]],
##     ID["EPSG",27700]]
# create dtm
dtm = grid_terrain(motte, 0.5, algorithm = knnidw(k = 6L, p = 2))

# addign coordinate system
crs(dtm) = CRS("+init=epsg:27700")
## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj =
## prefer_proj): Discarded datum OSGB_1936 in CRS definition
par(mfrow = c(1,2))
plot(dtm, main = "DTM", col = height.colors(50))
## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
## = prefer_proj): Discarded datum Unknown based on Airy 1830 ellipsoid in CRS
## definition
## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
## = prefer_proj): Discarded datum Unknown based on Airy 1830 ellipsoid in CRS
## definition

## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
## = prefer_proj): Discarded datum Unknown based on Airy 1830 ellipsoid in CRS
## definition
plot(dsm, main = "DSM",col = height.colors(50))
## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
## = prefer_proj): Discarded datum Unknown based on Airy 1830 ellipsoid in CRS
## definition

## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
## = prefer_proj): Discarded datum Unknown based on Airy 1830 ellipsoid in CRS
## definition

## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
## = prefer_proj): Discarded datum Unknown based on Airy 1830 ellipsoid in CRS
## definition

Hillshade

# dsm
slope_dsm = terrain(dsm, opt = 'slope')
## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
## = prefer_proj): Discarded datum Unknown based on Airy 1830 ellipsoid in CRS
## definition
aspect_dsm = terrain(dsm, opt = 'aspect')
## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
## = prefer_proj): Discarded datum Unknown based on Airy 1830 ellipsoid in CRS
## definition
hill_dsm = hillShade(slope_dsm, aspect_dsm, angle = 40, direction = 270)
## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
## = prefer_proj): Discarded datum Unknown based on Airy 1830 ellipsoid in CRS
## definition
# dtm
slope_dtm = terrain(dtm, opt = 'slope')
## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
## = prefer_proj): Discarded datum Unknown based on Airy 1830 ellipsoid in CRS
## definition
aspect_dtm = terrain(dtm, opt = 'aspect')
## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
## = prefer_proj): Discarded datum Unknown based on Airy 1830 ellipsoid in CRS
## definition
hill_dtm = hillShade(slope_dtm, aspect_dtm, angle = 5, direction = 270)
## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
## = prefer_proj): Discarded datum Unknown based on Airy 1830 ellipsoid in CRS
## definition
#plot
par(mfrow = c(1,2))
plot(hill_dtm, main = "DTM Hilshade", col = grey.colors(100, start = 0, end = 1), 
     legend = FALSE)
## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
## = prefer_proj): Discarded datum Unknown based on Airy 1830 ellipsoid in CRS
## definition

## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
## = prefer_proj): Discarded datum Unknown based on Airy 1830 ellipsoid in CRS
## definition

## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
## = prefer_proj): Discarded datum Unknown based on Airy 1830 ellipsoid in CRS
## definition
plot(hill_dsm, main = "DSM Hillshade", col = grey.colors(100, start = 0, end = 1))
## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
## = prefer_proj): Discarded datum Unknown based on Airy 1830 ellipsoid in CRS
## definition

## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
## = prefer_proj): Discarded datum Unknown based on Airy 1830 ellipsoid in CRS
## definition

## Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj
## = prefer_proj): Discarded datum Unknown based on Airy 1830 ellipsoid in CRS
## definition

3D Model

#And convert it to a matrix:
elmat = raster_to_matrix(dtm)

elmat %>%
  sphere_shade(texture = "imhof1") %>%
  add_shadow(ray_shade(elmat, zscale = 0.5, sunaltitude = 30,lambert = TRUE),
             max_darken = 1) %>%
  add_shadow(lamb_shade(elmat,zscale = 0.5,sunaltitude = 30), max_darken = 0.2) %>%
  add_shadow(ambient_shade(elmat, zscale = 0.5), max_darken = 0.2) %>%
  plot_3d(elmat, zscale = 0.5,windowsize = c(1000,1000),
          phi = 40, theta = 180, zoom = 0.8, fov = 1)
rglwidget()

Tantallon Castle And here is the code

library(rayshader)
library(raster)
library(magick)
library(gifski)

dem = raster("data/tantallon.tif")

n_frames <- 41

elmat = raster_to_matrix(dem)

zscale <- 0.5

waterdepthvalues <- c(0:20, seq(19,0,-1)) / 2

phi_values = seq(20,60)

waterdepthvalues * zscale

length(waterdepthvalues)

img_frames <- paste0("drain", seq_len(n_frames), ".png")

for (i in seq_len(n_frames)) {
elmat %>%
  sphere_shade(texture = "imhof1") %>%
  add_shadow(ray_shade(elmat, zscale = 0.5, sunaltitude = 30,lambert = TRUE),
             max_darken = 1) %>%
  add_shadow(lamb_shade(elmat,zscale = 0.5,sunaltitude = 30), max_darken = 0.2) %>%
  add_shadow(ambient_shade(elmat, zscale = 0.5), max_darken = 0.2) %>%
  plot_3d(elmat, zscale = 0.5,windowsize = c(1000,1000),
          water = TRUE, watercolor = "imhof3", wateralpha = 0.5, 
          waterlinecolor = "#ffffff", waterlinealpha = 0.5,
          waterdepth = waterdepthvalues[i],
          phi = 50, theta = 45, zoom = 0.8, fov = 1)
  render_snapshot(filename = img_frames[i],
                  title_text = "Tantallon Castle", 
                  title_font = "Helvetica",
                  vignette = TRUE,
                  title_size = 50,
                  title_color = "black")
  rgl::clear3d()
}

magick::image_write_gif(magick::image_read(img_frames), 
                        path = "tantallon.gif", 
                        delay = 6/n_frames)
 
Logo

Geographic Information Science and Analysis Team

LS0tCnRpdGxlOiAiU0cgTGlEQVIgaW4gUiAtIEJhc2ljIgphdXRob3I6ICJieSBNaWNoYWwgTWljaGFsc2tpIC0gYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiAlWScpYCIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IGZsYXRseQogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IHRydWUKICAgICAgc21vb3RoX3Njcm9sbDogZmFsc2UKICAKLS0tCgo8c3R5bGU+CgpkaXYuYmx1ZSB7IGNvbG9yOiAjRkZGRkZGIDtiYWNrZ3JvdW5kLWNvbG9yOiAjMjkzZTUxOyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7IH0KCjwvc3R5bGU+Cgo8ZGl2IGNsYXNzID0gImJsdWUiPgoKVGhpcyB0dXRvcmlhbCAuLi4gW1Njb3R0aXNoIFJlbW90ZSBTZW5zaW5nIFBvcnRhbF0oaHR0cHM6Ly9yZW1vdGVzZW5zaW5nZGF0YS5nb3Yuc2NvdC8pLgoKPC9kaXY+CgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCiMgUGFja2FnZXMKCmBgYHtyIHBhY2thZ2VzLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PUZBTFNFfQpsaWJyYXJ5KGxpZFIpIyBwcm9jZXNzIExBWiBmaWxlcwpsaWJyYXJ5KHJhc3RlcikjIGRlYWwgd2l0aCByYXN0ZXIKbGlicmFyeShyYXlzaGFkZXIpICMgM0Qgdml6CmxpYnJhcnkocmdsKSAjIGludGVyYWN0aXZlIHBsb3QKbGlicmFyeShzZikgIyBzcGF0aWFsIGNsYXNzCgpgYGAKCgojIEFyZWEgb2YgSW50ZXJlc3QKCmBgYHtyfQptb3R0ZV9wb2ludCA9IHN0X3JlYWQoImRhdGEvY2FubW9yZV9wb2ludC5zaHAiLCBxdWlldCA9IFRSVUUpCgptb3R0ZV9idWZmZXIgPSBzdF9idWZmZXIobW90dGVfcG9pbnQsZGlzdCA9IDUwKQoKYGBgCgojIExBWgoKTmV4dCwgSSBhbSByZWFkaW5nIHRoZSBMQVogZmlsZXMgYW5kIGNsaXBwaW5nIHRoZSBwb2ludCBjbG91ZCB0byB0aGUgZXh0ZW50IG9mIGltbWlkaWF0ZSBhcmVhIGFyb3VuZCB0aGUgbW90dGUuCmBgYHtyIGxhc30KI3JlYWQgbGF6IGZpbGVzCmxhcyA9IHJlYWRMQVMoImRhdGEvTlg2MDU1XzRQUE1fTEFTX1BIQVNFMy5sYXoiKQoKbW90dGUgPSBjbGlwX3JvaShsYXMsIG1vdHRlX2J1ZmZlcikKI3Bsb3QgbGlkYXIgcG9pbnQgY2xvdWQKcGxvdChtb3R0ZSwgYmcgPSAid2hpdGUiKQoKcmdsd2lkZ2V0KCkKCgoKYGBgCgo8cCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+Z3JhYiBhbmQgcm90YXRlIHRoZSBtb2RlbCAhIDwvYT48L3A+CgojIERpZ2l0YWwgRWxldmV0aW9uIE1vZGVsCgpJbiB0aGlzIHN0ZXAgSSBhbSBydW5uaW5nIHN0YW5kYXJkIGFsZ2hvcml0bXMgZnJvbSBMaURSIHBhY2thZ2UgdG8gY29tcHV0ZSBEaWdpdGFsIFN1cmZhY2UgTW9kZWwgKERTTSkgYW5kIERpZ2l0aWFsIFRlcnJhaW4gTW9kZWwgKERUTSkuCgpgYGB7cn0KcmdsLmNsZWFyKCkKIyBjcmVhdGUgZHNtIGFuZCBkdG0KZHNtID0gZ3JpZF9jYW5vcHkobW90dGUsIDAuNSwgcGl0ZnJlZSgpKQoKIyBhc3NpZ24gY29vcmRpbmF0ZSBzeXN0ZW0KY3JzKGRzbSkgPSBDUlMoIitpbml0PWVwc2c6Mjc3MDAiKQpzdF9jcnMoMjc3MDApCiMgY3JlYXRlIGR0bQpkdG0gPSBncmlkX3RlcnJhaW4obW90dGUsIDAuNSwgYWxnb3JpdGhtID0ga25uaWR3KGsgPSA2TCwgcCA9IDIpKQoKIyBhZGRpZ24gY29vcmRpbmF0ZSBzeXN0ZW0KY3JzKGR0bSkgPSBDUlMoIitpbml0PWVwc2c6Mjc3MDAiKQoKcGFyKG1mcm93ID0gYygxLDIpKQpwbG90KGR0bSwgbWFpbiA9ICJEVE0iLCBjb2wgPSBoZWlnaHQuY29sb3JzKDUwKSkKcGxvdChkc20sIG1haW4gPSAiRFNNIixjb2wgPSBoZWlnaHQuY29sb3JzKDUwKSkKCmBgYAoKIyBIaWxsc2hhZGUKCmBgYHtyfQojIGRzbQpzbG9wZV9kc20gPSB0ZXJyYWluKGRzbSwgb3B0ID0gJ3Nsb3BlJykKYXNwZWN0X2RzbSA9IHRlcnJhaW4oZHNtLCBvcHQgPSAnYXNwZWN0JykKaGlsbF9kc20gPSBoaWxsU2hhZGUoc2xvcGVfZHNtLCBhc3BlY3RfZHNtLCBhbmdsZSA9IDQwLCBkaXJlY3Rpb24gPSAyNzApCgojIGR0bQpzbG9wZV9kdG0gPSB0ZXJyYWluKGR0bSwgb3B0ID0gJ3Nsb3BlJykKYXNwZWN0X2R0bSA9IHRlcnJhaW4oZHRtLCBvcHQgPSAnYXNwZWN0JykKaGlsbF9kdG0gPSBoaWxsU2hhZGUoc2xvcGVfZHRtLCBhc3BlY3RfZHRtLCBhbmdsZSA9IDUsIGRpcmVjdGlvbiA9IDI3MCkKCiNwbG90CnBhcihtZnJvdyA9IGMoMSwyKSkKcGxvdChoaWxsX2R0bSwgbWFpbiA9ICJEVE0gSGlsc2hhZGUiLCBjb2wgPSBncmV5LmNvbG9ycygxMDAsIHN0YXJ0ID0gMCwgZW5kID0gMSksIAogICAgIGxlZ2VuZCA9IEZBTFNFKQpwbG90KGhpbGxfZHNtLCBtYWluID0gIkRTTSBIaWxsc2hhZGUiLCBjb2wgPSBncmV5LmNvbG9ycygxMDAsIHN0YXJ0ID0gMCwgZW5kID0gMSkpCmBgYAoKIyAzRCBNb2RlbAoKYGBge3J9CiNBbmQgY29udmVydCBpdCB0byBhIG1hdHJpeDoKZWxtYXQgPSByYXN0ZXJfdG9fbWF0cml4KGR0bSkKCmVsbWF0ICU+JQogIHNwaGVyZV9zaGFkZSh0ZXh0dXJlID0gImltaG9mMSIpICU+JQogIGFkZF9zaGFkb3cocmF5X3NoYWRlKGVsbWF0LCB6c2NhbGUgPSAwLjUsIHN1bmFsdGl0dWRlID0gMzAsbGFtYmVydCA9IFRSVUUpLAogICAgICAgICAgICAgbWF4X2RhcmtlbiA9IDEpICU+JQogIGFkZF9zaGFkb3cobGFtYl9zaGFkZShlbG1hdCx6c2NhbGUgPSAwLjUsc3VuYWx0aXR1ZGUgPSAzMCksIG1heF9kYXJrZW4gPSAwLjIpICU+JQogIGFkZF9zaGFkb3coYW1iaWVudF9zaGFkZShlbG1hdCwgenNjYWxlID0gMC41KSwgbWF4X2RhcmtlbiA9IDAuMikgJT4lCiAgcGxvdF8zZChlbG1hdCwgenNjYWxlID0gMC41LHdpbmRvd3NpemUgPSBjKDEwMDAsMTAwMCksCiAgICAgICAgICBwaGkgPSA0MCwgdGhldGEgPSAxODAsIHpvb20gPSAwLjgsIGZvdiA9IDEpCnJnbHdpZGdldCgpCmBgYAoKCiFbVGFudGFsbG9uIENhc3RsZV0oaW1nL3RhbnRhbGxvbi5naWYpCkFuZCBoZXJlIGlzIHRoZSBjb2RlCgpgYGB7ciwgZWNobz1UUlVFLCBldmFsPUZBTFNFfQpsaWJyYXJ5KHJheXNoYWRlcikKbGlicmFyeShyYXN0ZXIpCmxpYnJhcnkobWFnaWNrKQpsaWJyYXJ5KGdpZnNraSkKCmRlbSA9IHJhc3RlcigiZGF0YS90YW50YWxsb24udGlmIikKCm5fZnJhbWVzIDwtIDQxCgplbG1hdCA9IHJhc3Rlcl90b19tYXRyaXgoZGVtKQoKenNjYWxlIDwtIDAuNQoKd2F0ZXJkZXB0aHZhbHVlcyA8LSBjKDA6MjAsIHNlcSgxOSwwLC0xKSkgLyAyCgpwaGlfdmFsdWVzID0gc2VxKDIwLDYwKQoKd2F0ZXJkZXB0aHZhbHVlcyAqIHpzY2FsZQoKbGVuZ3RoKHdhdGVyZGVwdGh2YWx1ZXMpCgppbWdfZnJhbWVzIDwtIHBhc3RlMCgiZHJhaW4iLCBzZXFfbGVuKG5fZnJhbWVzKSwgIi5wbmciKQoKZm9yIChpIGluIHNlcV9sZW4obl9mcmFtZXMpKSB7CmVsbWF0ICU+JQogIHNwaGVyZV9zaGFkZSh0ZXh0dXJlID0gImltaG9mMSIpICU+JQogIGFkZF9zaGFkb3cocmF5X3NoYWRlKGVsbWF0LCB6c2NhbGUgPSAwLjUsIHN1bmFsdGl0dWRlID0gMzAsbGFtYmVydCA9IFRSVUUpLAogICAgICAgICAgICAgbWF4X2RhcmtlbiA9IDEpICU+JQogIGFkZF9zaGFkb3cobGFtYl9zaGFkZShlbG1hdCx6c2NhbGUgPSAwLjUsc3VuYWx0aXR1ZGUgPSAzMCksIG1heF9kYXJrZW4gPSAwLjIpICU+JQogIGFkZF9zaGFkb3coYW1iaWVudF9zaGFkZShlbG1hdCwgenNjYWxlID0gMC41KSwgbWF4X2RhcmtlbiA9IDAuMikgJT4lCiAgcGxvdF8zZChlbG1hdCwgenNjYWxlID0gMC41LHdpbmRvd3NpemUgPSBjKDEwMDAsMTAwMCksCiAgICAgICAgICB3YXRlciA9IFRSVUUsIHdhdGVyY29sb3IgPSAiaW1ob2YzIiwgd2F0ZXJhbHBoYSA9IDAuNSwgCiAgICAgICAgICB3YXRlcmxpbmVjb2xvciA9ICIjZmZmZmZmIiwgd2F0ZXJsaW5lYWxwaGEgPSAwLjUsCiAgICAgICAgICB3YXRlcmRlcHRoID0gd2F0ZXJkZXB0aHZhbHVlc1tpXSwKICAgICAgICAgIHBoaSA9IDUwLCB0aGV0YSA9IDQ1LCB6b29tID0gMC44LCBmb3YgPSAxKQogIHJlbmRlcl9zbmFwc2hvdChmaWxlbmFtZSA9IGltZ19mcmFtZXNbaV0sCiAgICAgICAgICAgICAgICAgIHRpdGxlX3RleHQgPSAiVGFudGFsbG9uIENhc3RsZSIsIAogICAgICAgICAgICAgICAgICB0aXRsZV9mb250ID0gIkhlbHZldGljYSIsCiAgICAgICAgICAgICAgICAgIHZpZ25ldHRlID0gVFJVRSwKICAgICAgICAgICAgICAgICAgdGl0bGVfc2l6ZSA9IDUwLAogICAgICAgICAgICAgICAgICB0aXRsZV9jb2xvciA9ICJibGFjayIpCiAgcmdsOjpjbGVhcjNkKCkKfQoKbWFnaWNrOjppbWFnZV93cml0ZV9naWYobWFnaWNrOjppbWFnZV9yZWFkKGltZ19mcmFtZXMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgcGF0aCA9ICJ0YW50YWxsb24uZ2lmIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGF5ID0gNi9uX2ZyYW1lcykKYGBgCgombmJzcDsKPGhyIC8+CjxjZW50ZXI+CjxpbWcgc3JjPSJodHRwczovL3JlbW90ZXNlbnNpbmdkYXRhLmdvdi5zY290L3Njb3Rnb3Zsb2dvLjM4YTczZjY4LnN2ZyIgYWx0ID0gIkxvZ28iIHdpZHRoPSIzMDAiIGhlaWdodD0iMTAwIj4KPC9jZW50ZXI+CjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXI7Ij5HZW9ncmFwaGljIEluZm9ybWF0aW9uIFNjaWVuY2UgYW5kIEFuYWx5c2lzIFRlYW08L3A+CjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXI7Ij48c3Bhbj48ZW0+R0ktU0FUQGdvdi5zY290PC9lbT48L3NwYW4+PC9wPgo=